package com.softhinker.ke24.unit3.engine;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.softhinker.ke24.unit3.listener.ResultListener;
import com.softhinker.ke24.unit3.listener.UserProfileListener;
import com.softhinker.ke24.unit3.model.Stock;
import com.softhinker.ke24.unit3.model.UserProfile;

import jess.Filter;
import jess.JessException;
import jess.Rete;
import jess.WorkingMemoryMarker;

public class InferenceEngine implements UserProfileListener {
	private Rete engine;
    private WorkingMemoryMarker marker;
    private ResultListener resultListener;
    private Database db = new Database();
    
    public InferenceEngine() throws JessException{
    	// Create a Jess rule engine
        engine = new Rete();
        engine.reset();

        // Load the pricing rules
        engine.batch("rules.clp");
//        engine.addAll(db.getStockList());
        
        // Mark end of catalog data for later
        marker = engine.mark();
    }
    
    public void setResultListener(ResultListener resultListener){
    	this.resultListener = resultListener;
    }

	@Override
	public void publishUserProfile(UserProfile userProfile) {
		System.out.println("Start Jess to inference...");
		try {
			// Remove any previous order data, leaving only catalog data
	    	engine.resetToMark(marker);
			
	    	// Add facts to working memory
	    	engine.add(userProfile.getGreedLevel());
	    	engine.add(userProfile.getAffordability());
	    	engine.add(userProfile.getProfessionLevel());
	    	
			// Fire the rules that apply to this order
	        engine.run();
	        
	        @SuppressWarnings("unchecked")
			Iterator<Stock> stockIterator = engine.getObjects(new Filter.ByClass(Stock.class));
	        if(this.resultListener != null && stockIterator != null){
	        	Map<String, Stock> stockMap = db.getStocks();
	        	List<Stock> stockList = new ArrayList<Stock>();
	        	Map<String, Stock> selectedStocks = new HashMap<String, Stock>();
	        	while(stockIterator.hasNext()){
	        		Stock s = stockIterator.next();
	        		Stock stock = stockMap.get(s.getCode());
	        		if(stock == null){
	        			System.out.println("==> cannot find the stock : " + s.getCode());
	        		} else{ 
	        			stock.setVotes(stock.getVotes() + 1);
	        			if(!selectedStocks.containsKey(stock.getCode())){
	        				stockList.add(stock);
	        			}
	        			selectedStocks.put(stock.getCode(), stock);
	        		}
	        	}
	        	Collections.sort(stockList);
	        	this.resultListener.publishResult(stockList);
	        }
		} catch (JessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
    
}
